<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <script type="text/javascript" src="../jsunit/app/jsUnitCore.js"></script>
    <script type="text/javascript" src="../../src/objx.js"></script>
    <script type="text/javascript" src="../../src/objx.test.js"></script>
    
    <script type="text/javascript">

		var counter = 0;
		var beforeCounter = 0;
		var afterCounter = 0;

		function test_namespace()
		{
			assertNotUndefined("objx.test", objx.test);
		}
		
		function test_assertSignature_works()
		{
		
			var foo = function(one, two, three){};
			assertSignature(foo, "one", "two", "three");
		
		}
		
		function test_assertSignature_wrongArgCount()
		{
		
			var foo = function(one, two, three){};
			
			assertThrowsAnyType("Exception expected to be thrown when assertSignature passed different arguments.", function(){
				assertSignature(foo, "one", "two");
			});
		
		}
		
		function test_assertSignature()
		{
		
			var foo = function(one, two, three){};
			
			assertThrowsAnyType("Exception expected to be thrown when assertSignature passed different arguments.", function(){
				assertSignature(foo, "one", "two", "four");
			});
			
			assertNotThrows("assertSignature not expected to throw an exception when the arguments match the signature.", function(){
				assertSignature(foo, "one", "two", "three");
			});
		
		}

		function test_addBeforeCode()
		{
		
			counter = 0;
			beforeCounter = 0;
		
			var myObj = {
				increaseAmount: 2,
				simpleMethod: function(){
					counter += this.increaseAmount;
					return 10;
				}
			};
			
			assertEquals(0, counter);
			assertEquals(0, beforeCounter);
			
			// call the method
			myObj.simpleMethod();
			
			// make sure it was called
			assertEquals(2, counter);
			
			// and the before one was not
			assertEquals(0, beforeCounter);
			
			// add the before code
			objx.test.addBefore(myObj, "simpleMethod", function(){
				beforeCounter++;
			});
			
			// call the method again
			var response = myObj.simpleMethod();
			
			// make sure the response was real
			assertEquals("The response was not real.", 10, response);
			
			// make sure it was called twice
			assertEquals(4, counter);
			
			// and the before one was called once
			assertEquals(1, beforeCounter);
						
		}
		
		function test_addAfterCode()
		{
		
			counter = 0;
			afterCounter = 0;
		
			var myObj = {
				simpleMethod: function(c){
					counter += c;
					return c;
				}
			};
			
			assertEquals(0, counter);
			assertEquals(0, afterCounter);
			
			// call the method
			myObj.simpleMethod(1);
			
			// make sure it was called
			assertEquals(1, counter);
			
			// and the before one was not
			assertEquals(0, afterCounter);
			
			// add the before code
			objx.test.addAfter(myObj, "simpleMethod", function(){
				afterCounter++;
			});
			
			// call the method again
			var response = myObj.simpleMethod(5);
			
			// make sure the response was real
			assertEquals("The response was not real.", 5, response);
			
			// make sure it was called twice
			assertEquals(6, counter);
			
			// and the before one was called once
			assertEquals(1, afterCounter);
						
		}

		function test_assertIsInterface()
		{
		
			assertThrowsAnyType("assertIsInterface should kick up a stink when asked to assert a non Interface object", function(){
				assertIsInterface( {} );
			});
			assertThrowsAnyType("assertIsInterface should kick up a stink when asked to assert 123", function(){
				assertIsInterface( 123 );
			});
			assertThrowsAnyType("assertIsInterface should kick up a stink when asked to assert a string", function(){
				assertIsInterface( "str" );
			});
			
			assertNotThrows("assertIsInterface shouldn't kick up a stink when asked to assert an Interface", function(){
				assertIsInterface( Interface({}) );
			});

		}
		
		function test_assertIsClass()
		{
		
			assertThrowsAnyType("assertIsClass should kick up a stink when asked to assert a non Class object", function(){
				assertIsClass( {} );
			});
			assertThrowsAnyType("assertIsClass should kick up a stink when asked to assert 123", function(){
				assertIsClass( 123 );
			});
			assertThrowsAnyType("assertIsClass should kick up a stink when asked to assert a string", function(){
				assertIsClass( "str" );
			});
			
			assertNotThrows("assertIsClass shouldn't kick up a stink when asked to assert a Class", function(){
				assertIsClass( Class({}) );
			});

		}
		
		function test_assertIsMethod()
		{
		
			assertThrowsAnyType("assertIsMethod should kick up a stink when asked to assert a non Method object", function(){
				assertIsMethod( {} );
			});
			assertThrowsAnyType("assertIsMethod should kick up a stink when asked to assert 123", function(){
				assertIsMethod( 123 );
			});
			assertThrowsAnyType("assertIsMethod should kick up a stink when asked to assert a string", function(){
				assertIsMethod( "str" );
			});
			
			assertNotThrows("assertIsMethod shouldn't kick up a stink when asked to assert a Method", function(){
				assertIsMethod( Method() );
			});

		}
		
		function test_assertIsEvent()
		{
		
			assertThrowsAnyType("assertIsEvent should kick up a stink when asked to assert a non Event object", function(){
				assertIsEvent( {} );
			});
			assertThrowsAnyType("assertIsEvent should kick up a stink when asked to assert 123", function(){
				assertIsEvent( 123 );
			});
			assertThrowsAnyType("assertIsEvent should kick up a stink when asked to assert a string", function(){
				assertIsEvent( "str" );
			});
			assertThrowsAnyType("assertIsEvent should kick up a stink when asked to assert a Class()", function(){
				assertIsEvent( Class() );
			});
			assertThrowsAnyType("assertIsEvent should kick up a stink when asked to assert a Interface()", function(){
				assertIsEvent( Interface() );
			});
			assertThrowsAnyType("assertIsEvent should kick up a stink when asked to assert a Method()", function(){
				assertIsEvent( Method() );
			});
			
			assertNotThrows("assertIsEvent shouldn't kick up a stink when asked to assert a Event", function(){
				assertIsEvent( Event() );
			});

		}
		
		
		function test_assertIsFunction(){
		
			assertThrowsAnyType("assertIsFunction should kick up a stink when asked to assert an object.", function(){
				assertIsFunction({});
			});
			assertThrowsAnyType("assertIsFunction should kick up a stink when asked to assert a number.", function(){
				assertIsFunction(123);
			});
			assertThrowsAnyType("assertIsFunction should kick up a stink when asked to assert a string.", function(){
				assertIsFunction("");
			});
			
			assertNotThrows("assertIsFunction shouldn't kick up a stink when asked to assert a real function", function(){
				assertIsFunction( function(){} );
			});

		}
		
		
		function test_addCallCounter()
		{
		
			normalCounter = 0;
			var o = {
			
				doSomething: function(){
					normalCounter++;
					return 99;
				}
			
			};
		
			objx.test.addCounter(o, "doSomething");
		
			// make sure this gave us a counters object
			assertNotUndefined("o.counters", o.countOf);
			assertNotUndefined("o.counters.doSomething", o.countOf.doSomething);
			assertEquals(0, o.countOf.doSomething);
			
			assertEquals("Response of counted method interrupted.", 99, o.doSomething());
			
			assertEquals(1, normalCounter);
			assertEquals(1, o.countOf.doSomething);

			assertEquals("Response of counted method interrupted.", 99, o.doSomething());
			
			assertEquals(2, normalCounter);
			assertEquals(2, o.countOf.doSomething);

			objx.test.addCounter(o, "doSomething");

			assertEquals("Response of counted method interrupted.", 99, o.doSomething());
			
			assertEquals(3, normalCounter);
			assertEquals(1, o.countOf.doSomething);
			
		}
		
		
		function test_interfaceStub(){
		
			var MyInterface = Interface({
			
				doSomething: Method(),
				doSomethingElse: Method(),
				onSomething: Event()
			
			});
		
			var stub = objx.test.interfaceStub(MyInterface);
			
			assertNotUndefined("stub.doSomething", stub.doSomething);
			assertNotUndefined("stub.doSomethingElse", stub.doSomethingElse);
			assertNotUndefined("stub.onSomething", stub.onSomething);

			assertNotUndefined("stub.countOf", stub.countOf);

			assertNotUndefined("stub.countOf.doSomething", stub.countOf.doSomething);
			assertNotUndefined("stub.countOf.doSomethingElse", stub.countOf.doSomethingElse);
			assertNotUndefined("stub.countOf.onSomething", stub.countOf.onSomething);
			
			assertNotUndefined("stub.countOf.actsAs", stub.countOf.actsAs);
            assertNotUndefined("stub.countOf.implements", stub.countOf.implements);
            assertNotUndefined("stub.countOf.observe", stub.countOf.observe);
            assertNotUndefined("stub.countOf.notify", stub.countOf.notify);

			stub.doSomething();
			stub.doSomething();
			stub.doSomething();
			
			stub.doSomethingElse();
			stub.doSomethingElse();
			
			stub.onSomething();
			stub.onSomething();
			stub.onSomething();
			stub.onSomething();
			stub.onSomething();
			
			assertEquals(3, stub.countOf.doSomething);
			assertEquals(2, stub.countOf.doSomethingElse);
			assertEquals(5, stub.countOf.onSomething);

		}
		
		function test_assertContainer_failure(){
		
			var threw = false;
			try{
				
				assertContains("123456", "678");
				
			}catch(e){
				threw = true;
			}
			
			if (!threw)
				fail("assertContains did not throw an exception when it should have.");
		
		}
		
		function test_assertContainer_success(){
		
			assertContains("123456", "123");
			assertContains("123456", "234");
			assertContains("123456", "345");
			assertContains("123456", "456");
		
		}
		

    </script>
</head>
<body>
</body>
</html>